<?php
namespace App\ModelStatistic;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Input;


class IncreaseNewPlayer extends  Model{
    protected $table='increase_player';
    protected $_db_select = '';
    const DB_FIELDS = "area,new_time,new_num,day1,day2,day3,day4,day5,day6,day7,day14,day30,cache";
    const STATISTIC_DAY = [1,2,3,4,5,6,7,14,30];
    const RETAIN_STEP = 1 * 86400;

    // const UPDATED_AT = null;
    // const CREATED_AT = null;
	public function paginate()
    {
        
        
    	$perPage = Request::get('per_page', 100);

        $page = Request::get('page', 1);
        
        $start = ($page-1)*$perPage;

        //$qdCond = StatisticCommon::remainChartDate(Request::get('retain_time'));
        $new_time = Request::get('new_time');
        $qdCond = StatisticCommon::RetainWeekPeriod(Request::get('area', 0), $new_time['start'] ?: strtotime("-6 days"));
        
        // 查询6个周的留存
        if (0 != ($qdCond['code'])){
            admin_toastr($qdCond['msg'] . $qdCond['code'],'error');
            return $paginator = new LengthAwarePaginator([], 0, $perPage);
        }
        $tableAccount = 'increase_player';

        $rw = \DB::connection($this->selectdb())->table($tableAccount);
        $rw = $rw->where('area', intval(Request::get("area")));
        // 自定义时间查询
        if (isset($qdCond['start'])) {
            //$rw->where('reg_time', '>=', "0");
            $rw->whereRaw("new_time >= '{$qdCond['start']}'");
        }

        if (isset($qdCond['end'])) {
            //$rw->where('reg_time', '<=', "{$qdRond['end']}");
            $rw->whereRaw("new_time <= '{$qdCond['end']}'");
        }
        //$result = \DB::connection($this->selectdb())->select($sql);

        $rw->orderBy('new_time', 'asc');
        $rw->skip($page* $perPage - $perPage)->take($perPage);
        $result = $rw->get();

        $result = $result->toArray();

        \Log::debug(__METHOD__,['generate start',  $rw->toSql(), $qdCond]);
        self::Generate(intval(Request::get("area")), $qdCond['start'], $qdCond['end'], $result);
        \Log::debug(__METHOD__, ['generate end', []]);
        
        $total = $rw->count();

        $list = static::hydrate($result);

        $paginator = new LengthAwarePaginator($list, $total, $perPage);

        $paginator->setPath(url()->current());

        return $paginator;
    }

    public static function with($relations)
    {
        return new static;
    }


    public function selectdb(){
        if ($this->_db_select) {
            return $this->_db_select;
        }
        //\App\Models\Area::RemoteBgsiSelectByArea(Input::get('area'));
        $this->_db_select = 'mysql_statistic';
        return $this->_db_select;
    }

    public function getConnectionName(){
        
        return $this->selectdb();
    }

    // 生成周留存
    public static function Generate($area, $start, $start_end, $data)
    {
        // 开始时间 和 区服未选择的话，直接只做查询不做统计
        if (!$start || !$area || $start > $start_end){
            \Log::debug(__METHOD__, ["mabay empty start:" . $start, "mabay empty area:".$area, "so cant generate statistic data"]);
            return;
        }
        $cur_int = strtotime(date("Y-m-d"));
        $list = self::GenerateSource($data);
        $main_loop = self::GetMainGenerateLoop($start, $start_end);
        \Log::debug(__METHOD__, [$list]);
        for($step = 0; $step < $main_loop['end_count']; $step++)
        {
            $tmp_int = $start + $step * self::RETAIN_STEP;
            $obj = null;
            if (empty($list[$tmp_int])){
                //$list[$tmp_int] = new self();
                $list[$tmp_int]['new_time'] = $tmp_int;
                $list[$tmp_int]['area'] = $area;
            }
            
            $obj = $list[$tmp_int];
            $changed = false;
            !$obj['area'] && $obj['area'] = $area;
            // 表示是当天统计的  再次看的时候要重新查 注册数
            if ($obj['new_num'] <= 0 || $obj['new_time'] == strtotime(date("Y-m-d"))){
                $obj['new_num'] = (self::GetPlayersByNew($area, $obj['new_time']));
                $changed = true;
            }
            
            if ($tmp_int == $cur_int && intval($obj['new_num']) > 0){
                $obj['new_num'] *= -1;
            }
            $tttt = date('Y-m-d',$tmp_int);
            \Log::debug(__METHOD__, ["STEP[{$tttt}]", $obj['new_num']]);
            if ($obj['new_num'] == 0){
                continue;
            }
            self::FieldLoopLogic($obj, $changed, $tmp_int,$area);

            if ($changed){
                self::SaveByArray($obj);
            }
        }
    }

    public static function GenerateSource($data)
    {
        $list = [];
        foreach($data as $item){
            $item = (array)$item;
            $list[$item['new_time']] = $item;
            $list[$item['new_time']]['cache'] = $item['cache'] ? json_decode($item['cache'], true) : [];
        }
        return $list;
    }

    //
    public static function QueryTimePeriod($retain_time, $step)
    {
        $end = $retain_time + $step - 1;
        $start = date("Y-m-d 00:00:00", $retain_time);
        $end  = date("Y-m-d H:i:s", $end);

        return ['start' => $start, 'end' => $end];
    }

    // 获取留存比较日的 注册用户数
    public static function GetPlayersByNew($area, $new_time)
    {
        static $p_arr = [];
        $period = self::QueryTimePeriod($new_time, self::RETAIN_STEP);

        if (!empty($p_arr[$new_time])){
            return $p_arr[$new_time];
        }

        $data = \DB::connection('remote_bgsi')->table('user_login')->select('player_id')->whereBetween('reg_time',$period)->groupBy("player_id")->get();
        
        $count = $data->count();
        
        $p_arr[$new_time] = $count;
        \Log::debug(__METHOD__, ['END',\Config::get("database.connections.remote_bgsi.host"), $period, $p_arr]);
        return $count;
    }

    public static function GetMemberNum($area, $login_time)
    {
        
        if (!$area || !$login_time ){
            return 0;
        }
       
        $period = self::QueryTimePeriod($login_time, self::RETAIN_STEP);

        $rw = \DB::connection('remote_bgsi')->table('user_login')->whereBetween('reg_time',$period)->groupBy('player_id')->get();
    
        $rtn = $rw->count();
        \Log::debug(__METHOD__, ['get login num END', ($rtn), $period]);
        
        return ($rtn) ?: 0;
    }
    public static function GetMainGenerateLoop($start, $end)
    {
        $start = strtotime(date("Y-m-d", $start));
        $end = strtotime(date("Y-m-d", $end));
        $end_count = ($end - $start)/self::RETAIN_STEP;
        // 最多做100条统计
        ($end_count > 100) && $end_count = 100;
        return ['start' => $start, 'end' => $end, 'end_count' => $end_count];  
    }

    
    public static function FieldLoopLogic(&$data, &$save_change, $retain_time, $area)
    {
        $cur_int =  strtotime(date("Y-m-d"));
        foreach(self::STATISTIC_DAY as $day){
                
            // 切割每个属性 是统计属性的 去处理
            $obj_attr = 'day_'.$day;

            // 统计日期大于当前时间，直接过跳过循环
            $cur_day_tmp_int = $retain_time + self::RETAIN_STEP * $day;
           
            if ($cur_day_tmp_int > $cur_int) {
                break;
            }
            
            // 大于0值 表示 正确的且不会再改变 不需要再查询
            // 等于0值 标志位是 已查过， 则不用去再查询
            if ($data[$obj_attr] > 0 || $data['cache'][$obj_attr] == 1){
                continue;
            }

            $equal_cur_op = 1;// 表示与查询日期相等， 如果是1 表示不相等 -1 表示相等 是临时数据
            if ($cur_day_tmp_int == $cur_int) {
                $equal_cur_op = -1;
            }

            $member_num = self::GetMemberNum($area, $cur_day_tmp_int);
            $data[$obj_attr] = $member_num * $equal_cur_op;
            \Log::debug(__METHOD__, [$member_num, date('Y-m-d',$cur_day_tmp_int)]);
            // 当未有更改的时候不做保存 这里有问题当留存人数就是0的 每次都需要查询会很慢
            
            $save_change = true;
            
            // 0值 保存 查询状态 下次不用查
            ($data[$obj_attr] == 0) && $data['cache'][$obj_attr] = 1;
        }
    }

    public function AssignData($one, $data)
    {
        foreach($data as $fld => $value)
        {
            $one->$fld = $value;
        }

        if (!empty($data['cache'])) {
            $one->cache = $data['cache'];
        }
    }

    public static function SaveByArray($data)
    {
        if (!$data["new_time"]){
            return ;
        }
        $data['new_time'] + self::RETAIN_STEP;
        $one = self::find($data["id"]) ?:new self;
        $one->AssignData($one, $data);
        if (!is_string($data['cache'])){
            $one->cache = json_encode($one->cache);
        }
        \Log::debug(__METHOD__, [$data]);
        $one->save();
    }
}